package com.xiaoshuidi.cloud.module.member.repository;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.framework.fadada.core.enums.IdentTypeEnum;
import com.xiaoshuidi.cloud.framework.fadada.core.service.dto.PersonDTO;
import com.xiaoshuidi.cloud.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.xiaoshuidi.cloud.framework.redis.lock.DistributeLock;
import com.xiaoshuidi.cloud.module.member.api.user.dto.*;
import com.xiaoshuidi.cloud.module.member.controller.app.user.vo.AppUserInfoRespVO;
import com.xiaoshuidi.cloud.module.member.controller.app.user.vo.MemberPageReqVO;
import com.xiaoshuidi.cloud.module.member.controller.app.user.vo.MemberUpdateStateVO;
import com.xiaoshuidi.cloud.module.member.controller.app.user.vo.MemberVO;
import com.xiaoshuidi.cloud.module.member.convert.user.UserConvert;
import com.xiaoshuidi.cloud.module.member.enums.UserStateEnum;
import com.xiaoshuidi.cloud.module.member.mapper.MemberUserMapper;
import com.xiaoshuidi.cloud.module.member.pojo.user.MemberAuthentication;
import com.xiaoshuidi.cloud.module.member.pojo.user.MemberUser;
import com.xiaoshuidi.cloud.module.member.utils.CardUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Repository
@RequiredArgsConstructor
@Slf4j
public class MemberUserRepository extends ServiceImpl<MemberUserMapper, MemberUser> {
    private final MemberUserMapper mapper;

    public static final String ADD_USER = "user:add:";//新增用户

    public boolean updateMemberUserAuthStatus(MemberAuthentication memberAuthentication, PersonDTO personCertInfo) {
        if (ObjectUtils.isNotEmpty(personCertInfo)) {
            LambdaUpdateWrapper<MemberUser> wrapper = new LambdaUpdateWrapper<MemberUser>().eq(MemberUser::getId, memberAuthentication.getUserId())
                    .set(MemberUser::getAuthenticated, true)
                    .set(MemberUser::getAuthenticatedTime, LocalDateTime.now())
                    .set(StringUtils.isNotBlank(personCertInfo.getBirthday()), MemberUser::getBirthday, StringUtils.isNotBlank(personCertInfo.getBirthday()) ? LocalDateTimeUtil.parseDate(personCertInfo.getBirthday()) : null)
                    .set(StringUtils.isNotBlank(personCertInfo.getFork()), MemberUser::getFork, personCertInfo.getFork())
                    .set(StringUtils.isNotBlank(personCertInfo.getSex()), MemberUser::getGender, StringUtils.isNotBlank(personCertInfo.getSex()) ? Integer.valueOf(personCertInfo.getSex()) : null)
                    .set(StringUtils.isNotBlank(personCertInfo.getPersonName()), MemberUser::getName, personCertInfo.getPersonName())
                    .set(StringUtils.isNotBlank(personCertInfo.getPersonName()), MemberUser::getNickname, personCertInfo.getPersonName())
                    .set(StringUtils.isNotBlank(personCertInfo.getIdCard()), MemberUser::getCardNo, personCertInfo.getIdCard())

                    .set(StringUtils.isNotEmpty(personCertInfo.getAddress()), MemberUser::getAddress, personCertInfo.getAddress());

            if (StringUtils.isNotEmpty(personCertInfo.getCertType())) {
                //如果0：身份证；
                //1：护照；
                //B：港澳居民来往内地通行证号;
                //C：台湾居民来往大陆通行证
                if (personCertInfo.getCertType().equals(IdentTypeEnum.ID_NO.getCode())) {
                    wrapper.set(MemberUser::getCardType, "1");
                } else if (personCertInfo.getCertType().equals(IdentTypeEnum.PASSPORT_NO.getCode())) {
                    wrapper.set(MemberUser::getCardType, "2");
                } else if (personCertInfo.getCertType().equals(IdentTypeEnum.HOME_VISITING_NO.getCode())) {
                    wrapper.set(MemberUser::getCardType, "4");
                } else if (personCertInfo.getCertType().equals(IdentTypeEnum.TAIWANESE_SYNDROME_NO.getCode())) {
                    wrapper.set(MemberUser::getCardType, "3");
                }

            }

            try {
                if (StringUtils.isNotEmpty(personCertInfo.getIdCard()) && StringUtils.isNotEmpty(personCertInfo.getCertType()) && personCertInfo.getCertType().equals(IdentTypeEnum.ID_NO.getCode())) {
                    //算出年龄
                    int age = CardUtils.countAge(personCertInfo.getIdCard());
                    String birthday = CardUtils.getBirthdayFromCard(personCertInfo.getIdCard());
                    wrapper.set(MemberUser::getBirthday, StringUtils.isNotEmpty(birthday) ? LocalDate.parse(birthday) : null);
                    wrapper.set(MemberUser::getAge, age);
                }
            } catch (Exception e) {
                log.error("年龄计算失败！");
            }

            //todo如果有地址插入地址表里
            mapper.update(null, wrapper);
//        //如果有地址，需要更新地址
//        if (StringUtils.isNotEmpty(personCertInfo.getAddress())){
//            //1.查询用户地址如果没有则新增为默认，其他地址
//        }
        } else {
            LambdaUpdateWrapper<MemberUser> wrapper = new LambdaUpdateWrapper<MemberUser>().eq(MemberUser::getId, memberAuthentication.getUserId())
                    .set(MemberUser::getAuthenticated, true)
                    .set(MemberUser::getAuthenticatedTime, LocalDateTime.now());
            mapper.update(null, wrapper);
        }
        return true;
    }

    public PageResult<MemberVO> getMemberPage(MemberPageReqVO memberPageReqVo) {
        LambdaQueryWrapper<MemberUser> wrapper = new LambdaQueryWrapper<MemberUser>()
                .ge(ObjectUtils.isNotEmpty(memberPageReqVo.getBeginTime()), MemberUser::getCreateTime, memberPageReqVo.getBeginTime())
                .le(ObjectUtils.isNotEmpty(memberPageReqVo.getEndTime()), MemberUser::getCreateTime, memberPageReqVo.getEndTime())
                .eq(ObjectUtils.isNotEmpty(memberPageReqVo.getAuthenticated()), MemberUser::getAuthenticated, memberPageReqVo.getAuthenticated())
                .and(StringUtils.isNotEmpty(memberPageReqVo.getKeyWord()), m -> m.like(MemberUser::getName, memberPageReqVo.getKeyWord())
                        .or().like(MemberUser::getNickname, memberPageReqVo.getKeyWord())
                        .or().like(MemberUser::getMobile, memberPageReqVo.getKeyWord())
                        .or().like(MemberUser::getCardNo, memberPageReqVo.getKeyWord()));
        PageResult<MemberUser> page = mapper.selectPage(memberPageReqVo, wrapper);
        List<MemberVO> collect = page.getList().stream().map(m -> {
            MemberVO memberVO = new MemberVO();
            BeanUtils.copyProperties(m, memberVO);
            return memberVO;
        }).collect(Collectors.toList());
        PageResult<MemberVO> result = PageResult.empty();
        result.setList(collect);
        result.setTotal(page.getTotal());
        return result;
    }

    public Boolean validateUser(String mobile) {
        //判断此用户是否存在
        MemberUser memberUser = mapper.selectOne(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getMobile, mobile));
        if (ObjectUtils.isNotEmpty(memberUser) && ObjectUtils.isNotEmpty(memberUser.getStatus())
                && memberUser.getStatus().intValue() == UserStateEnum.INVALID.getCode().intValue()) {
            return false;
        }
        return true;
    }

    public MemberUserRespDTO getUserInfo(MemberUserReqDTO req) {
        String key = ADD_USER.concat(req.getMobile());
        try (DistributeLock lock = DistributeLock.getLock(key)) {
            if (lock.tryLock()) {
                MemberUserRespDTO memberUserRespDTO = new MemberUserRespDTO();
                List<MemberUser> users = mapper.selectList(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getMobile, req.getMobile())
                        .eq(MemberUser::getStatus, UserStateEnum.INUSE.getCode()));
                if (users != null && users.size() > 0) {
                    MemberUser user = users.get(0);
                    if (!user.getAuthenticated()) {
                        user.setNickname(req.getName());
                        user.setName(req.getName());
                    } else {
                        user.setNickname(req.getName());
                    }
                    if (ObjectUtils.isNotEmpty(req.getCompanyId())) {
                        user.setSuperId(req.getCompanyId());
                    }
                    if (StringUtils.isNotEmpty(req.getEmail())) {
                        user.setEmail(req.getEmail());
                    }
                    if (ObjectUtils.isNotEmpty(req.getEducation())) {
                        user.setEducation(req.getEducation());
                    }
                    if (req.getEmergencyContacts() != null && req.getEmergencyContacts().size() > 0) {
                        user.setEmergencyContact(JsonUtils.toJsonString(req.getEmergencyContacts()));
                    }
                    if (StringUtils.isNotEmpty(req.getWorkUnit())) {
                        user.setWorkUnit(req.getWorkUnit());
                    }
                    //没有实名认证
                    if (ObjectUtils.isNotEmpty(req.getAddress()) && !user.getAuthenticated()) {
                        user.setAddress(req.getAddress());
                    }

                    if (StringUtils.isNotEmpty(req.getCardNo()) && !user.getAuthenticated()) {
                        user.setCardNo(req.getCardNo());
                        user.setCardType("1");
                    }
                    mapper.updateById(user);
                    BeanUtils.copyProperties(user, memberUserRespDTO);
                    if (StringUtils.isNotEmpty(user.getEmergencyContact())) {
                        List<EmergencyContact> emergencyContacts = JsonUtils.parseArray(user.getEmergencyContact(), EmergencyContact.class);
                        memberUserRespDTO.setEmergencyContacts(emergencyContacts);
                    }
                } else {
                    MemberUser memberUserDO = new MemberUser();
                    memberUserDO.setStatus(UserStateEnum.INUSE.getCode());
                    memberUserDO.setAuthenticated(false);
                    memberUserDO.setNickname(req.getName());
                    memberUserDO.setName(req.getName());
                    memberUserDO.setLoginDate(LocalDateTime.now());
                    memberUserDO.setMobile(req.getMobile());
                    if (StringUtils.isNotEmpty(req.getEmail())) {
                        memberUserDO.setEmail(req.getEmail());
                    }
                    if (ObjectUtils.isNotEmpty(req.getEducation())) {
                        memberUserDO.setEducation(req.getEducation());
                    }
                    if (req.getEmergencyContacts() != null && req.getEmergencyContacts().size() > 0) {
                        memberUserDO.setEmergencyContact(JsonUtils.toJsonString(req.getEmergencyContacts()));
                    }
                    if (StringUtils.isNotEmpty(req.getWorkUnit())) {
                        memberUserDO.setWorkUnit(req.getWorkUnit());
                    }
                    //没有实名认证
                    if (ObjectUtils.isNotEmpty(req.getAddress())) {
                        memberUserDO.setAddress(req.getAddress());
                    }
                    if (ObjectUtils.isNotEmpty(req.getCompanyId())) {
                        memberUserDO.setSuperId(req.getCompanyId());
                    }
                    if (StringUtils.isNotEmpty(req.getCardNo())) {
                        memberUserDO.setCardNo(req.getCardNo());
                        memberUserDO.setCardType("1");
                    }
                    mapper.insert(memberUserDO);
                    BeanUtils.copyProperties(memberUserDO, memberUserRespDTO);
                }
                return memberUserRespDTO;
            }
        }
        return null;
    }

    public AppUserInfoRespVO getUserInfoById(Long id) {
        MemberUser memberUser = mapper.selectById(id);
        AppUserInfoRespVO appUserInfoRespVO = new AppUserInfoRespVO();
        BeanUtils.copyProperties(memberUser, appUserInfoRespVO);
        if (StringUtils.isNotEmpty(memberUser.getEmergencyContact())) {
            List<EmergencyContact> emergencyContacts = JsonUtils.parseArray(memberUser.getEmergencyContact(), EmergencyContact.class);
            appUserInfoRespVO.setEmergencyContacts(emergencyContacts);
        }
        return appUserInfoRespVO;
    }

    public Boolean memberUpdateState(MemberUpdateStateVO memberUpdateStateVO) {
        MemberUser memberUser = new MemberUser();
        memberUser.setId(memberUpdateStateVO.getId());
        memberUser.setStatus(memberUpdateStateVO.getStatus());
        if (memberUpdateStateVO.getStatus().intValue() == 2 && StringUtils.isNotEmpty(memberUpdateStateVO.getDisableDesc())) {
            memberUser.setDisableDesc(memberUpdateStateVO.getDisableDesc());
        }
        mapper.updateById(memberUser);
        return true;
    }

    public MemberUserAuthInfoDTO getUserAuthInfo(String moible) {
        return mapper.getUserAuthInfo(moible);
    }

    public PageResult<MemberUserRespDTO> getUserPage(MemberUserPageDTO page) {
        LambdaQueryWrapper<MemberUser> wrapper = new LambdaQueryWrapper<MemberUser>()
                .ge(ObjectUtils.isNotEmpty(page.getBeginTime()), MemberUser::getCreateTime, page.getBeginTime())
                .le(ObjectUtils.isNotEmpty(page.getEndTime()), MemberUser::getCreateTime, page.getEndTime())
                .eq(ObjectUtils.isNotEmpty(page.getAuthenticated()), MemberUser::getAuthenticated, page.getAuthenticated())
                .and(StringUtils.isNotEmpty(page.getName()), m -> m.like(MemberUser::getName, page.getName())
                        .or().like(MemberUser::getNickname, page.getName()))
                .like(StringUtils.isNotEmpty(page.getMobile()), MemberUser::getMobile, page.getMobile());
        PageResult<MemberUser> pageResult = mapper.selectPage(page, wrapper);
        List<MemberUserRespDTO> collect = pageResult.getList().stream().map(m -> {
            MemberUserRespDTO dto = new MemberUserRespDTO();
            BeanUtils.copyProperties(m, dto);
            if (StringUtils.isNotEmpty(m.getEmergencyContact())) {
                List<EmergencyContact> emergencyContacts = JsonUtils.parseArray(m.getEmergencyContact(), EmergencyContact.class);
                dto.setEmergencyContacts(emergencyContacts);
            }
            return dto;
        }).collect(Collectors.toList());
        PageResult<MemberUserRespDTO> result = PageResult.empty();
        result.setList(collect);
        result.setTotal(pageResult.getTotal());
        return result;
    }

    public List<MemberUserRespDTO> getUsersByIds(List<Long> ids) {
        List<MemberUser> memberUsers = mapper.selectBatchIds(ids);
        List<MemberUserRespDTO> collect = memberUsers.stream().map(m -> {
            MemberUserRespDTO dto = new MemberUserRespDTO();
            BeanUtils.copyProperties(m, dto);
            if (StringUtils.isNotEmpty(m.getEmergencyContact())) {
                List<EmergencyContact> emergencyContacts = JsonUtils.parseArray(m.getEmergencyContact(), EmergencyContact.class);
                dto.setEmergencyContacts(emergencyContacts);
            }
            return dto;
        }).collect(Collectors.toList());
        return collect;
    }

    public MemberUserRespDTO getUsersById(Long id) {
        MemberUser user = mapper.selectById(id);
        return UserConvert.INSTANCE.convert2(user);
    }

    public MemberUser getUserByMobile(String mobile) {
        LambdaQueryWrapper<MemberUser> wrapper = new LambdaQueryWrapperX<MemberUser>()
                .eqIfPresent(MemberUser::getMobile, mobile)
                .eq(MemberUser::getStatus, UserStateEnum.INUSE.getCode());
        List<MemberUser> list = mapper.selectList(wrapper);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    public List<MemberUser> getBirthDayUser() {
        LambdaQueryWrapper<MemberUser> wrapper = new LambdaQueryWrapperX<MemberUser>()
                .isNotNull(MemberUser::getBirthday);
        List<MemberUser> users = mapper.selectList(wrapper);
        return users;
    }

    public void deleteOldMoible(MemberUser old) {
        mapper.deleteOldMoible(old);
    }

    public void cancelInvalid(String mobile) {
        mapper.cancelInvalid(mobile);
    }

    public MemberUser getUserByCardNo(String card, String passPort, String hkCard, String twCard) {
        LambdaQueryWrapper<MemberUser> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ObjectUtils.isNotEmpty(card), MemberUser::getCardNo, card)
                .or()
                .eq(ObjectUtils.isNotEmpty(passPort), MemberUser::getCardNo, passPort)
                .or()
                .eq(ObjectUtils.isNotEmpty(hkCard), MemberUser::getCardNo, hkCard)
                .or()
                .eq(ObjectUtils.isNotEmpty(twCard), MemberUser::getCardNo, twCard);
        wrapper.orderByDesc(MemberUser::getCreateTime);
        wrapper.last("limit 1");
        return mapper.selectOne(wrapper);
    }
}
